package com.cps.platform.service.config.spi;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.cps.platform.core.BaseService;
import com.cps.platform.core.Constant;
import com.cps.platform.core.Mapbean;
import com.cps.platform.core.hbase.HbasePut;
import com.cps.platform.core.json.JsonParserUtil;
import com.cps.platform.core.util.ReadProperties;
import com.cps.platform.core.util.ValidateUtil;
import com.cps.platform.service.config.IConfigService;

/**
 * <p>
 * 文件名称: DefaultConfigService.java
 * </p>
 * <p>
 * 文件描述: 默认的配置服务实现
 * <p>
 * 版权所有: 版权所有(C)2011
 * </p>
 * <p>
 * 公 司: 联通系统集成有限公司
 * </p>
 * <p>
 * 内容摘要: 配置服务数据使用HBASE存储，ROWKEY即服务ID。
 * 		配置也负责HBASE数据表的创建等功能。
 * </p>
 * <p>
 * 其他说明: 
 * 在RelyHbase rely = new RelyHbase(configTableName, appId, 
		super.serviceId, super.authToken, tenantId);中，为什么appId使用配置的ID?
		服务的使用者使用的是配置服务，如果未授权使用hbase存储服务则服务异常。内部服务
		之间的调用关系不应该抛出给服务的使用者。
 * </p>
 * <p>
 * 完成日期：2012-12-6
 * </p>
 * 
 * @author ChenZhang
 */
@Component
@Path("/configService")
public class DefaultConfigService extends BaseService implements IConfigService{

	private static Logger log = Logger.getLogger(DefaultConfigService.class);
	//将配置服务作为一个内部租户，这样就可以使用其它服务
	private final String tenantId = "configTenant";
	//配置数据存储的HBASE的表名
	private String configTableName;

	DefaultConfigService(){
		initConfig();
	}

	@Override
	protected void init(){
		try{
			configTableName = Constant.paasconfig;
			
			log.info("DefaultConfigService initial success. ");
		}catch(Exception e) {
			log.info("DefaultConfigService initial failed. ");
			log.error(e.getMessage());
			throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).build());
		}
	}

	@Override
	protected void setServiceId() {
		ReadProperties readProperties = new ReadProperties("config.properties");
		String servicesJson = readProperties.readValue(Constant.platformServices);
		Mapbean mapBean = (Mapbean) JsonParserUtil.getMapbean(servicesJson);
		super.serviceId = (String) mapBean.getMap().get(Constant.platformServicesId);
		super.authToken = (String) mapBean.getMap().get(Constant.platformServicesToken);
	}

	@Override
	public String getConfig(String appId, String authToken) {
		if(ValidateUtil.isNull(appId, authToken, tenantId)){
			throw new WebApplicationException(Response.status(Status.BAD_REQUEST).build());
		}
		
		try{
			RelyHbase rely = new RelyHbase(configTableName, appId, 
					super.serviceId, super.authToken, tenantId);
			HbasePut put = rely.getConfig();
			if(put!=null) {
				Mapbean mapBean = new Mapbean();
				Map<String, Object> map = new HashMap<String, Object>();
				map.putAll(put.getKeyValues());
				mapBean.setMap(map);
				return JsonParserUtil.getJsonFromObject(mapBean);
			}else{
				log.info("The service '"+serviceId+"' could not be found!");
				return null;
			}
		} catch (Exception e) {
			log.error("Get config data [serviceId:"+serviceId+"] failed. The reason is "+ e.getMessage());
			throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).build());
		}
	}
	

	@Override
	public String getConfigByKey(String appId, String authToken, String key) {
		String all = this.getConfig(appId, authToken);
		if(!ValidateUtil.isNull(all)) {
			Mapbean mapBean = (Mapbean) JsonParserUtil.getObjectFromJson(all, Mapbean.class);
			return (String) mapBean.getMap().get(key);
		}else{
			return null;
		}
	}

	@Override
	public Response saveConfig(String appId, String authToken,
			String key, String value) {
		if(ValidateUtil.isNull(appId, authToken, tenantId)){
			return Response.status(Status.BAD_REQUEST).build(); 
		}
		
		try{
			RelyHbase rely = new RelyHbase(configTableName, appId, 
					super.serviceId, super.authToken, tenantId);
			HbasePut put = rely.addConfig(key, value);
			log.info("Save config data success. "+put.getRowKey());
			return Response.ok(key).build();
		} catch (Exception e) {
			log.error("Save config data [serviceId:"+serviceId+",key:"+key+",value:"+value+"] failed. The reason is "+ e.getMessage());
			throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).build());
		}
	}

	@Override
	public Response removeConfig(String appId, String authToken, String key) {
		if(ValidateUtil.isNull(appId, authToken, tenantId)){
			return Response.status(Status.BAD_REQUEST).build(); 
		}
		
		try{
			RelyHbase rely = new RelyHbase(configTableName, appId, 
					super.serviceId, super.authToken, tenantId);
			HbasePut put = rely.removeConfig(key);
			log.info("Remove config data ["+serviceId+"]["+key+"] success. " + JsonParserUtil.getJsonFromObject(put));
			return Response.ok(key).build();
		} catch (Exception e) {
			log.error("Remove config data [serviceId:"+serviceId+",key:"+key+"] failed. The reason is "+ e.getMessage());
			throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).build());
		}
	}

	@Override
	public Response removeConfig(String appId, String authToken) {
		if(ValidateUtil.isNull(appId, authToken, tenantId)){
			return Response.status(Status.BAD_REQUEST).build(); 
		}
		
		try{
			RelyHbase rely = new RelyHbase(configTableName, appId, 
					super.serviceId, super.authToken, tenantId);
			boolean result = rely.removeConfig();
			log.error("Remove config data [serviceId:"+serviceId+"] success. The reason is " + result);
			
			return Response.ok(result).build();
		} catch (Exception e) {
			log.error("Remove config data [serviceId:"+serviceId+"] failed. The reason is "+ e.getMessage());
			throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).build());
		}
	}

	@Override
	public String getServiceBaseAddress() {
		ReadProperties readProperties = new ReadProperties("config.properties");
		
		String addressJson = readProperties.readValue(Constant.serviceBaseAddress);
		
		StringBuffer addressBuffer = new StringBuffer();
		addressBuffer.append("{\"map\":").append(addressJson).append("}");
		
		return addressBuffer.toString();
	}
	
}
